/*
 * comlan
 */

package com.promfy.net.apn;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

public class ApnSettings {

	private static final String TAG = "apn";
	private Context context;

	public ApnSettings(Context context ) {
		super();
		this.context = context;
	}
	
	/**
	 * self check about net connection.
	 * @param callback2 
	 * @param callback 
	 * @param context
	 * @return
	 */
	public void netSelfChecking(){
		Apn apnDB = null;
		Apn apnSP = null;
		try {
			apnDB = getApnFromDB(context);
			apnSP = getApnFromSP(context);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(apnDB == null && apnSP == null){
			//callback error
			Log.d(TAG, "netSelfChecking() callback error execute! (apnDB == null && apnSP == null)");
		}else if(apnDB == null){
			Log.d(TAG, "netSelfChecking() initApn() execute! (apnDB == null)");
			initApn(context,apnSP);
		}else if(!compareApn(apnDB,apnSP)){
			Log.d(TAG, "netSelfChecking() initApn() execute! (!compareApn(apnDB,apnSP))");
			initApn(context,apnSP);
		}
		
		checkMobileDataEnable(context);
		
		Log.d(TAG, "netSelfChecking() register net listener() ");


	}


	
	/****************************** base method **********************************/
	 /**
	  * check if mobile data is disable, set it enable. 
	  */
	 private void checkMobileDataEnable(Context context) {
	  ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

	  Class<?> conMgrClass = null; // ConnectivityManager
	  Field iConMgrField = null; // field in ConnectivityManager
	  Object iConMgr = null; // instance IConnectivityManager 
	  Class<?> iConMgrClass = null; // instance IConnectivityManager
	  Method setMobileDataEnabledMethod = null; // method setMobileDataEnabled 
	  Method getMobileDataEnabledMethod = null; // method getMobileDataEnabled 

	  try {
	   // get ConnectivityManager
	   conMgrClass = Class.forName(conMgr.getClass().getName());
	   // get ConnectivityManager.mService
	   iConMgrField = conMgrClass.getDeclaredField("mService");
	   // set mService accessible
	   iConMgrField.setAccessible(true);
	   // get instance of mService IConnectivityManager
	   iConMgr = iConMgrField.get(conMgr);
	   // get IConnectivityManager
	   iConMgrClass = Class.forName(iConMgr.getClass().getName());
	   // get IConnectivityManager.setMobileDataEnabled(boolean)
	   setMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
	   getMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod("getMobileDataEnabled", null);
	   Log.d(TAG, "getMobileDataEnabled = " + (Boolean)getMobileDataEnabledMethod.invoke(iConMgr, null));
	   if(!(Boolean)getMobileDataEnabledMethod.invoke(iConMgr, null)){		   
		   //set setMobileDataEnabled accesible
		   setMobileDataEnabledMethod.setAccessible(true);
		   //ivoke
		   setMobileDataEnabledMethod.invoke(iConMgr, true);
	   }
	  } catch (Exception e) {
		  e.printStackTrace();
	  }
	 }

	/**
	 * compare apn
	 */
	private boolean compareApn(Apn apnDB, Apn apnSP) {
		boolean isEqual = false;
		if(apnDB.toString().equals(apnSP.toString())){
			isEqual = true;
		}else{
			isEqual = false;
		}
		return isEqual;
	}
   
	/**
	 * get apn data form SharedPreference
	 * @param context
	 * @return
	 */
	private Apn getApnFromSP(Context context) throws Exception {
		makeTestDataForSP(context);
		
		Apn apn = null;
		SharedPreferences sp = context.getSharedPreferences("apn", Context.MODE_WORLD_WRITEABLE);
		if (sp == null){
			return apn;
		}
		apn = new Apn(sp.getString("name", ""),
					sp.getString("mcc", ""),
					sp.getString("mnc", ""),
					sp.getString("apn", ""),
					sp.getString("user", ""), 
					sp.getString("server", ""),
					sp.getString("password", ""),
					sp.getString("proxy", ""),
					sp.getString("port", ""),
					sp.getString("mmsproxy", ""),
					sp.getString("mmsport", ""),
					sp.getString("mmsc", ""),
					sp.getInt("authtype", -1),
					sp.getString("type", ""),
					sp.getInt("current", 1));
		Log.d(TAG, "getApnFromSP = \n" + apn);
		return apn;
	}

	/**
	 * make SharedPreference data for test.
	 * @param context
	 */
	private void makeTestDataForSP(Context context)  throws Exception {
		// 0. make sp for test.
		SharedPreferences sp = context.getSharedPreferences("apn", Context.MODE_WORLD_WRITEABLE);
		Editor edit = sp.edit();
		edit.putString("name", "xxx");
		edit.putString("mcc", "460");
		edit.putString("mnc", "01");
		edit.putString("apn", "3gnet");
		edit.putString("user", "");
		edit.putString("server", "");
		edit.putString("password", "");
		edit.putString("proxy", "");
		edit.putString("port", "80");
		edit.putString("mmsproxy", "");
		edit.putString("mmsport", "");
		edit.putString("mmsc", "");
		edit.putInt("authtype", -1);
		edit.putString("type", "default,dun");
		edit.putInt("current", 1);
		edit.commit();
	}

	/**
	 * get apn data from db in telephony.
	 * @param context
	 * @return
	 */
	private Apn getApnFromDB(Context context)  throws Exception {
		Apn apn = null;
		Cursor cursor = null;
		ContentResolver resolver = context.getContentResolver();
		
		cursor = resolver.query(Uri.parse("content://telephony/carriers"), null, "current=?", new String[] { "1" }, null);
		while(cursor.moveToNext()){
			apn = new Apn(cursor.getString(cursor.getColumnIndex("name")),
					cursor.getString(cursor.getColumnIndex("mcc")),
					cursor.getString(cursor.getColumnIndex("mnc")),
					cursor.getString(cursor.getColumnIndex("apn")),
					cursor.getString(cursor.getColumnIndex("user")), 
					cursor.getString(cursor.getColumnIndex("server")),
					cursor.getString(cursor.getColumnIndex("password")),
					cursor.getString(cursor.getColumnIndex("proxy")),
					cursor.getString(cursor.getColumnIndex("port")),
					cursor.getString(cursor.getColumnIndex("mmsproxy")),
					cursor.getString(cursor.getColumnIndex("mmsport")),
					cursor.getString(cursor.getColumnIndex("mmsc")),
					cursor.getInt(cursor.getColumnIndex("authtype")),
					cursor.getString(cursor.getColumnIndex("type")),
					cursor.getInt(cursor.getColumnIndex("current")));
			Log.d(TAG, "getApnFromDB = \n" + apn);
		}
		return apn;
	}

	/**
	 * 
	 * @param context
	 * @param apn
	 */
	public void initApn(Context context, Apn apn) {

		// 1. get apn from sp
		if (apn == null)
			return;

		// 2. update current apn
		ContentResolver resolver = context.getContentResolver();
		resolver.delete(Uri.parse("content://telephony/carriers"), "current=?", new String[] { "1" });

		// 3. set new apn
		try {
			insertApn(context, apn);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}  
	
	/**
     * insert data in telephony.db. system will fresh apn selection.
     * @param apn
     * @throws Exception
     */
    private void insertApn(Context context, Apn apn) throws Exception{
    	ContentResolver resolver = context.getContentResolver();
		ContentValues values = new ContentValues();
		values.put("name", apn.getName());
		values.put("numeric", apn.getMcc() + apn.getMnc());
		values.put("mcc", apn.getMcc());
		values.put("mnc", apn.getMnc());
		values.put("apn", apn.getApn());
		values.put("user", apn.getUser());
		values.put("server", apn.getServer());
		values.put("password", apn.getPassword());
		values.put("proxy", apn.getProxy());
		values.put("port", apn.getPort());
		values.put("mmsproxy", apn.getMmsproxy());
		values.put("mmsport", apn.getMmsport());
		values.put("mmsc", apn.getMmsc());
		values.put("authtype", apn.getAuthtype());
		values.put("type", apn.getType());
		values.put("current", apn.getCurrent());
		resolver.insert(Uri.parse("content://telephony/carriers"), values);
    }
    
	/**
	 * check if net is available, inner method.
	 */
	private boolean isNetAvailable(Context context){
		ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo info = connectivityManager.getActiveNetworkInfo();
		if (info == null || !info.isAvailable()) {
			return false;
		} else {
			return true;
		}
	}
    
}
